<template>
  <div class="the-code-editor-container" ref="container"></div>
</template>

<script>
import * as monaco from 'monaco-editor'
const sqlStr =
  'methods DM.add DM.del'
export default {
  name: 'codeEditor',
  props: {
    options: {
      type: Object,
      default() {
        return {
          language: 'javascript',
          readOnly: true,
          theme: 'vs-dark'
        }
      }
    },
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      monacoInstance: null,
      provider: null,
      hints: [
         'methods',
        'computed',
        'data',
        'watch',
        'beforeCreate',
        'beforeMount',
        'created',
        'mounted',
        'beforeUpdate',
        'updated',
        'beforeDestroy',
        'destroyed'  
      ]
    }
  },
  created() {
    this.initHints()
  },
  mounted() {
    this.init()
  },
  beforeDestroy() {
    this.dispose()
  },

  methods: {
    dispose() {
      if (this.monacoInstance) {
        if (this.monacoInstance.getModel()) {
          this.monacoInstance.getModel().dispose()
        }
        this.monacoInstance.dispose()
        this.monacoInstance = null
        if (this.provider) {
          this.provider.dispose()
          this.provider = null
        }
      }
    },
    initHints() {
      const sqlArr = sqlStr.split(' ')
      this.hints = Array.from(new Set([...this.hints, ...sqlArr])).sort()
    },
    init() {
      const that = this
      this.dispose()
      const createCompleters = (textUntilPosition) => {
        // 过滤特殊字符
        const _textUntilPosition = textUntilPosition
          // .replace(/[[\]@\$\(\)]/g, '')
          .replace(/(\s+|\.)/g, ' ')
        const arr = _textUntilPosition.split(' ')
        const activeStr = arr[arr.length - 1]
        const len = activeStr.length

        // 获得编辑区域内已经存在的内容
        const rexp = new RegExp('([^\\w]|^)' + activeStr + '\\w*', 'gim')
        const match = that.value.match(rexp)
        const _hints = !match
          ? []
          : match.map((ele) => {
            const rexp = new RegExp(activeStr, 'gim')
            const search = ele.search(rexp)
            return ele.substr(search)
          })
        // 查找匹配当前输入值的元素
        const hints = Array.from(new Set([...that.hints, ..._hints]))
          .sort()
          .filter((ele) => {
            const rexp = new RegExp(ele.substr(0, len), 'gim')
            return (match && match.length === 1 && ele === activeStr) ||
              ele.length === 1
              ? false
              : activeStr.match(rexp)
          })
        // 添加内容提示
        const res = hints.map((ele) => {
          return {
            label: ele,
            kind:
              that.hints.indexOf(ele) > -1
                ? monaco.languages.CompletionItemKind.Keyword
                : monaco.languages.CompletionItemKind.Text,
            documentation: ele,
            insertText: ele
          }
        })
        return res
      }
      this.provider = monaco.languages.registerCompletionItemProvider(
        'javascript',
        {
          provideCompletionItems(model, position) {
            var textUntilPosition = model.getValueInRange({
              startLineNumber: position.lineNumber,
              startColumn: 1,
              endLineNumber: position.lineNumber,
              endColumn: position.column
            })
            var suggestions = createCompleters(textUntilPosition)
            return {
              suggestions: suggestions
            }
          }
        }
      )
      // 初始化编辑器实例
      this.monacoInstance = monaco.editor.create(this.$refs.container, {
        value: this.value,
        theme: 'vs-dark',
        autoIndex: true,
        ...this.options
      })

      // 监听编辑器content变化事件
      this.monacoInstance.onDidChangeModelContent(() => {
        this.$emit('contentChange', this.monacoInstance.getValue())
      })
    }
  }
}
</script>

<style scope>
.the-code-editor-container {
  width: 100%;
  height: 100%;
  overflow: hidden;
  border: 1px solid #eaeaea;
}
</style>
